package it.allerj.common.i18n;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.Map.Entry;

public final class StaticString implements Serializable {
	private static final long serialVersionUID = 1L;
	private static Map<String, ResourceBundle> resources = new HashMap<String, ResourceBundle>();
	private final static StaticString staticString = new StaticString();
	private static BundleMap _labels;
	
	private StaticString() {}
	public static String getString(String key, Object params[], Locale locale) {
		String label = "__NOLABEL__";
		if (resources.size() == 0)
			System.out.println(staticString.getClass().getName() + ": no bundle initialized");
		else {
			for (Iterator<String> keyActualBoudleIt = resources.keySet().iterator(); keyActualBoudleIt.hasNext();) {
				String keyActualBoudle = keyActualBoudleIt.next();
				try {
					label = BundleUtil.getMessageResourceString(resources.get(keyActualBoudle),key, params, locale);
					break;
				} catch (MissingResourceException ex) {
					// System.out.println(staticString.getClass().getName()+": no mach for key "+key+" in "+keyActualBoudle);
				}
			}
		}
		return ("__NOLABEL__".equals(label)) ? key : label;
	}
	
	public static String getString(String key) {
		return getString(key, null, null);
	}

	public static void setBundle(Set<String> bundleURLs) {
		/*
		 * if(resources.keySet().size()>0) return;
		 */
		for (Iterator<String> bundleURLsIt = bundleURLs.iterator(); bundleURLsIt.hasNext();) {
			String bundleURL = bundleURLsIt.next();
			try {
				resources.put(bundleURL, Utf8ResourceBundle.getBundle(bundleURL));
			} catch (MissingResourceException ex) {
				// System.out.println(staticString.getClass().getName()+": unable to find bundle "+bundleURL); 
			}
		}
	}

	public static String resolveString(String key) {
		String value = getString(key);
		return (value != null && !value.equals(key) ? value : null);
	}

	public static Map<String, ResourceBundle> getBundleMap() {
		return resources;
	}

	public static Map getLabels() {
		return _labels;
	}

	public static void initBundleMap() {
		_labels = new BundleMap();
	}

	private static class BundleMap implements Map<Object, Object> {

		private List<String> _values;

		// Optimized methods

		public Object get(Object key) {
			Object returnValue = null;
			try {
				for (Iterator<String> keyActualBoudleIt = resources.keySet().iterator(); keyActualBoudleIt.hasNext();) {
					ResourceBundle _bundle = resources.get(keyActualBoudleIt.next());
					returnValue = _bundle.getObject(key.toString());
					if (returnValue != null)
						break;
				}
				return returnValue;
			} catch (Exception e) {
				return "MISSING: " + key + " :MISSING";
			}
		}

		public boolean isEmpty() {
			boolean returnValue = true;
			for (Iterator<String> keyActualBoudleIt = resources.keySet().iterator(); keyActualBoudleIt.hasNext();) {
				ResourceBundle _bundle = resources.get(keyActualBoudleIt.next());
				returnValue = _bundle.getKeys().hasMoreElements();
				if (returnValue)
					break;
			}
			return !returnValue;
		}

		public boolean containsKey(Object key) {
			boolean returnValue = false;
			try {
				for (Iterator<String> keyActualBoudleIt = resources.keySet().iterator(); keyActualBoudleIt.hasNext();) {
					ResourceBundle _bundle = resources.get(keyActualBoudleIt.next());
					returnValue = _bundle.getObject(key.toString()) != null;
					if (returnValue)
						break;
				}
				return returnValue;
			} catch (MissingResourceException e) {
				return false;
			}
		}

		// Unoptimized methods

		public Collection values() {
			if (_values == null) {
				_values = new ArrayList<String>();
				for (Iterator<String> keyActualBoudleIt = resources.keySet().iterator(); keyActualBoudleIt.hasNext();) {
					ResourceBundle _bundle = resources.get(keyActualBoudleIt.next());
					for (Enumeration enumer = _bundle.getKeys(); enumer.hasMoreElements();) {
						String v = _bundle.getString((String) enumer.nextElement());
						_values.add(v);
					}
				}
			}
			return _values;
		}

		public int size() {
			return values().size();
		}

		public boolean containsValue(Object value) {
			return values().contains(value);
		}

		public Set entrySet() {
			Set<Entry> set = new HashSet<Entry>();
			for (Iterator<String> keyActualBoudleIt = resources.keySet().iterator(); keyActualBoudleIt.hasNext();) {
				final ResourceBundle _bundle = resources.get(keyActualBoudleIt.next());
				for (Enumeration enumer = _bundle.getKeys(); enumer.hasMoreElements();) {
					final String k = (String) enumer.nextElement();
					set.add(new Map.Entry() {
						public Object getKey() {
							return k;
						}

						public Object getValue() {
							return _bundle.getObject(k);
						}

						public Object setValue(Object value) {
							throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
						}
					});
				}
			}
			return set;
		}

		public Set keySet() {
			Set set = new HashSet();
			for (Iterator<String> keyActualBoudleIt = resources.keySet().iterator(); keyActualBoudleIt.hasNext();) {
				ResourceBundle _bundle = resources.get(keyActualBoudleIt.next());
				for (Enumeration enumer = _bundle.getKeys(); enumer.hasMoreElements();) {
					set.add(enumer.nextElement());
				}
			}
			return set;
		}

		// Unsupported methods

		public Object remove(Object key) {
			throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
		}

		public void putAll(Map t) {
			throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
		}

		public Object put(Object key, Object value) {
			throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
		}

		public void clear() {
			throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
		}
	}
}
